/*
    Estado        Metodo
    P           obtenerCategoria - Diego
    P           obtenerCategoriaPorHijo - Diego
    P           obtenerCategoriasRelacionadas - Diego
    P?           insertarCategoria - Diego (ver tema de multi acceso)
    P           listarCategorias - Diego
    P           listarCategoriasSinArticulo - Diego
    ?P?         listarCategoriasPorPadreYCampania - Diego
    P           listarCategoriasSinCategoriasHijas - Diego
    P           modificarCategoria - Diego
    P           eliminarCategoria - Diego
    P           hayArticulosConCategoria - Diego
 */

package dal;

import bd.BoundParam;
import bd.ConexionAvw;
import bd.ParamCallable;
import bd.Procedimientos;

import excepciones.AvwException;

import java.sql.SQLException;


import java.sql.ResultSet;

import java.util.ArrayList;

import java.util.logging.Level;
import java.util.logging.Logger;

import negocio.CampaniaWeb;
import negocio.CategoriaWeb;
import negocio.Marca;
import oracle.jdbc.driver.OracleTypes;
import util.Recurso;

import util.Utiles;

public class CategoriaDAL {
    
    static final Logger logger = Utiles.iniciarLogger("CategoriaDAL", false);
    
    public CategoriaDAL() {
    }

     /**
     * Lista todas las categorias existentes en el sistema
     * @return ArrayList de objetos CategoriaWeb.
     */
    public static ArrayList<CategoriaWeb> listarCategorias()throws AvwException {
        ArrayList<CategoriaWeb> categorias = new ArrayList<CategoriaWeb>();
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        ConexionAvw conexion = new ConexionAvw();
        ArrayList<ParamCallable> params = new ArrayList<ParamCallable>();

        try {
            logger.info("Consulto todas las Categorias");
            int pos=0;
            params.add(new ParamCallable(++pos,null,OracleTypes.CURSOR,ParamCallable.OUT));
            conexion.abrirConexion();
            rs = conexion.getCallableStatement(Procedimientos.CATEGORIAS_LISTAR,params,1);
            
            while (rs.next()) {
                CategoriaWeb categoriaWeb = new CategoriaWeb();
                
                categoriaWeb.setCawCodigo(rs.getString("caw_codigo"));
                categoriaWeb.setCawNombre(rs.getString("caw_nombre"));
                categoriaWeb.setCawCategoriaPadre(new CategoriaWeb(rs.getString("caw_categoria_padre")));
                categoriaWeb.setCawPalabrasClaves(rs.getString("caw_palabras_claves"));
                
                categorias.add(categoriaWeb);
            }
        } catch (SQLException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            throw new AvwException(e);
        } finally {
            conexion.cerrarConexion();
        }
        
        return categorias;
    }


    /**
     * Lista todas las categorias existentes en el sistema
     * @return ArrayList de objetos CategoriaWeb.
     */
    public static ArrayList<CategoriaWeb> listarCategoriasFiltro(int opcionFiltro, String filtro)throws AvwException {
        ArrayList<CategoriaWeb> categorias = new ArrayList<CategoriaWeb>();
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        ConexionAvw conexion = new ConexionAvw();
        
        sql.append("SELECT ");
        sql.append("caw.caw_codigo, ");
        sql.append("caw.caw_nombre, ");
        sql.append("caw.caw_categoria_padre, ");
        sql.append("cawP.caw_nombre, ");
        sql.append("caw.caw_palabras_claves ");
        sql.append("FROM ");
        sql.append("categorias_web caw, ");
        sql.append("categorias_web cawP ");
        sql.append("WHERE caw.caw_categoria_padre = cawP.caw_codigo (+)");
        sql.append("AND ");
        switch (opcionFiltro) {
            case 0:
                sql.append(" (caw.caw_codigo LIKE '%");
                sql.append(filtro.toUpperCase());
                sql.append("%'");
                sql.append("OR caw.caw_nombre LIKE '%");
                sql.append(filtro.toUpperCase());
                sql.append("%')");
                break;
            case 1:
                sql.append(" caw.caw_codigo LIKE '%");
                sql.append(filtro.toUpperCase());
                sql.append("%'");
                break;
            case 2:
                sql.append(" caw.caw_nombre LIKE '%");
                sql.append(filtro.toUpperCase());
                sql.append("%'");
                break;
            case 3:
                sql.append(" caw.caw_categoria_padre LIKE '%");
                sql.append(filtro.toUpperCase());
                sql.append("%'");
                break;
            case 4:
                sql.append(" caw.caw_palabras_claves LIKE '%");
                sql.append(filtro.toUpperCase());
                sql.append("%'");
                break;
            case 5:
                break;
            default:
                break;
        }
        sql.append("ORDER BY caw.caw_nombre ");
        try {
            logger.info("Consulto todas las Categorias");
            logger.info(sql.toString());
            conexion.abrirConexion();
            rs = conexion.getPreparedStatementResultSet(sql, null);
            
            while (rs.next()) {
                CategoriaWeb categoriaWeb = new CategoriaWeb();
                
                categoriaWeb.setCawCodigo(rs.getString("caw_codigo"));
                categoriaWeb.setCawNombre(rs.getString("caw_nombre"));
                CategoriaWeb categoriaPadre = new CategoriaWeb(rs.getString("caw_categoria_padre"));
                categoriaPadre.setCawNombre(rs.getString(4));
                categoriaWeb.setCawCategoriaPadre(categoriaPadre);
                categoriaWeb.setCawPalabrasClaves(rs.getString("caw_palabras_claves"));
                
                categorias.add(categoriaWeb);
            }
        } catch (SQLException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            throw new AvwException(e);
        } finally {
            conexion.cerrarConexion();
        }
        
        return categorias;
    }
    /**
     * Verifica si la categoria del objeto CategoriaWeb
     * enviada por parametro posee alguna categorria hija.
     * @param objeto CategoriaWeb (con solo el codigo).
     * @return ArrayList<CategoriaWeb> con las categoriasHijas
     */
    public static ArrayList<CategoriaWeb> listarCategoriasHijas(CategoriaWeb categoriaWeb, CampaniaWeb campaniaWeb, Marca marca) throws AvwException {
       ArrayList<CategoriaWeb> categorias = new ArrayList<CategoriaWeb>();
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        ConexionAvw conexion = new ConexionAvw();
        ArrayList params = new ArrayList();
        int pos =0;
        Recurso procedimiento = new Recurso("categoriadal.properties");
        try {
            logger.info("Consulto Categorias hijas ");
            params.add(new ParamCallable(++pos,null,OracleTypes.CURSOR,ParamCallable.OUT));
            params.add(new ParamCallable(++pos,campaniaWeb.getCamCodigo(),OracleTypes.VARCHAR,ParamCallable.IN));
            params.add(new ParamCallable(++pos,categoriaWeb.getCawCodigo(),OracleTypes.VARCHAR,ParamCallable.IN));
            
            conexion.abrirConexion();
            rs = conexion.getCallableStatement(procedimiento.obtenerPropiedad("listarCategoriasHijas"),params,1);
            
            while(rs.next()){
                CategoriaWeb categoria = new CategoriaWeb(rs.getString("caw_codigo"));
                categoria.setCawNombre(rs.getString("caw_nombre"));
                categoria.setCawCategoriaPadre(new CategoriaWeb(rs.getString("caw_categoria_padre")));
                categoria.setCawNivel(rs.getInt("nivel"));
                categorias.add(categoria);
            }
            
        } catch (SQLException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            logger.info(sql.toString());
            throw new AvwException(e.getMessage(), e, true);
            //out.println(e.getMessage());
        } finally {
            conexion.cerrarConexion();
        }
        return categorias;
    }

    /**
     * Verifica si la categoria del objeto CategoriaWeb
     * enviada por parametro posee algun articulo relacionado.
     * @param objeto CategoriaWeb (con solo el codigo).
     * @return ArrayList de objetos CategoriaWeb.
     */
    public static void hayArticulosConCategoria(CategoriaWeb categoriaWeb) throws AvwException {
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        ArrayList params = new ArrayList();
        ConexionAvw conexion = new ConexionAvw();
        int pos = 0;
        
        try {
            logger.info("Consulto Categoria con articulos? ");
            conexion.abrirConexion();
            params.add(new ParamCallable(++pos,categoriaWeb.getCawCodigo(),OracleTypes.NUMBER,ParamCallable.IN));
            params.add(new ParamCallable(++pos,null,OracleTypes.NUMBER,ParamCallable.OUT));
            int i = conexion.getIntCallableStatement(Procedimientos.HAY_ARTICULOS_CON_CATEGORIAS,params,2);

            if ( i == 0){
                logger.log(Level.INFO, "NO HAY articulos para esa Categoria");
                throw new AvwException("",false);
            }else{
                logger.log(Level.INFO, "HAY articulos para esa Categoria");
            }
            
        } catch (SQLException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            logger.info(sql.toString());
            throw new AvwException(e.getMessage(), e, true);
            //out.println(e.getMessage());
        } finally {
            conexion.cerrarConexion();
        }
    }
    
    /**
     * Verifica si la categoria del objeto CategoriaWeb
     * enviada por parametro posee algun articulo relacionado
     * de la campania enviada por parametro.
     * @param objeto CategoriaWeb (con solo el codigo).
     * @param objeto CampaniaWeb (con solo el codigo).
     * @return ArrayList de objetos CategoriaWeb.
     */
    public static void hayArticulosCampaniaConCategoria(CategoriaWeb categoriaWeb,
            CampaniaWeb campaniaWeb) throws AvwException {

        ArrayList<ParamCallable> params = new ArrayList<ParamCallable>();
        ConexionAvw conexion = new ConexionAvw();
        int pos = 0;
/*        
        sql.append("SELECT acw.art_codigo ");
        sql.append("FROM articulos_categorias_web acw, articulos_campanias ac ");
        sql.append("WHERE acw.art_codigo = ac.art_codigo ");
        sql.append("AND ac.cam_codigo LIKE ? AND acw.caw_codigo LIKE ?");

        
        params.add(new BoundParam(1,Utiles.noNull(campaniaWeb.getCamCodigo()),java.sql.Types.VARCHAR));
        params.add(new BoundParam(2,Utiles.noNull(categoriaWeb.getCawCodigo()),java.sql.Types.VARCHAR));
*/
        
        
        try {
            params.add(new ParamCallable(++pos,null,OracleTypes.NUMBER,ParamCallable.OUT));
            params.add(new ParamCallable(++pos,campaniaWeb.getCamCodigo(),OracleTypes.VARCHAR,ParamCallable.IN));
            params.add(new ParamCallable(++pos,categoriaWeb.getCawCodigo(),OracleTypes.VARCHAR,ParamCallable.IN));
            logger.info("Consulto Categoria con articulos? ");
            conexion.abrirConexion();
            int hay = conexion.getIntCallableStatement(Procedimientos.HAY_ARTICULOS_CAMPANIA_CON_CATEGORIA,params,1);
            
            if (hay == 0){
                logger.log(Level.INFO, "NO HAY articulos para esa categoria y campania");
                throw new AvwException("No hay articulos", true);
            }else{
                logger.log(Level.INFO, "HAY articulos para esa categoria y campania");
            }
            
        } catch (SQLException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            throw new AvwException(e.getMessage(), e, true);
            //out.println(e.getMessage());
        } finally {
            conexion.cerrarConexion();
        }
    }
    
    /**
     * Obtiene una lista de las categorias que no tienen articulos relacionados.
     * @return array de objetos CategoriaWeb.
     */
    public static ArrayList<CategoriaWeb> listarCategoriasSinArticulo()throws AvwException {
        ArrayList<CategoriaWeb> categorias = new ArrayList<CategoriaWeb>();
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        ConexionAvw conexion = new ConexionAvw();
        
        sql.append("SELECT ");
        sql.append("caw_codigo, ");
        sql.append("caw_nombre, ");
        sql.append("caw_categoria_padre, ");
        sql.append("caw_palabras_claves ");
        sql.append("FROM categorias_web ");
        sql.append("WHERE caw_codigo ");
        sql.append("NOT IN( ");
        sql.append("SELECT ");
        sql.append("caw_codigo ");
        sql.append("FROM articulos_categorias_web ");
        sql.append(") ");
        
        try {
            logger.info("Consulto todas las Categorias");
            logger.info(sql.toString());
            conexion.abrirConexion();
            rs = conexion.getPreparedStatementResultSet(sql, null);
            
            while (rs.next()) {
                CategoriaWeb categoriaWeb = new CategoriaWeb();
                
                categoriaWeb.setCawCodigo(rs.getString("caw_codigo"));
                categoriaWeb.setCawNombre(rs.getString("caw_nombre"));
                categoriaWeb.setCawCategoriaPadre(new CategoriaWeb(rs.getString("caw_categoria_padre")));
                categoriaWeb.setCawPalabrasClaves(rs.getString("caw_palabras_claves"));
                
                categorias.add(categoriaWeb);
            }
        } catch (SQLException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            throw new AvwException(e);
        } finally {
            conexion.cerrarConexion();
        }
        
        return categorias;
    }
    
    /**
     * Obtiene una lista de las categorias que no tienen padre.
     * @return array de objetos CategoriaWeb.
     */
    public static ArrayList<CategoriaWeb> listarCategoriasSinPadre()throws AvwException {
        ArrayList<CategoriaWeb> categorias = new ArrayList<CategoriaWeb>();
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        ConexionAvw conexion = new ConexionAvw();
        
        sql.append("SELECT caw_codigo, caw_nombre, caw_categoria_padre, caw_palabras_claves ");
        sql.append("FROM categorias_web ");
        sql.append("WHERE caw_categoria_padre is null ");
 
        try {
            logger.info("Consulto todas las Categorias");
            logger.info(sql.toString());
            conexion.abrirConexion();
            rs = conexion.getPreparedStatementResultSet(sql, null);
            
            while (rs.next()) {
                CategoriaWeb categoriaWeb = new CategoriaWeb();
                
                categoriaWeb.setCawCodigo(rs.getString("caw_codigo"));
                categoriaWeb.setCawNombre(rs.getString("caw_nombre"));
                categoriaWeb.setCawCategoriaPadre(new CategoriaWeb(rs.getString("caw_categoria_padre")));
                categoriaWeb.setCawPalabrasClaves(rs.getString("caw_palabras_claves"));
                
                categorias.add(categoriaWeb);
            }
        } catch (SQLException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            throw new AvwException(e);
        } finally {
            conexion.cerrarConexion();
        }
        
        return categorias;
    }

    /**
     * Inserta en el sistema la Categoria pasado por parametro.
     * @return objeto CategoriaWeb con el objeto CategoriaWeb padre
     * y el array de objetos CategoriaWeb de las categorias relacionadas.
     */
    public static void insertarCategoria(CategoriaWeb categoriaWeb) throws AvwException {
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        ConexionAvw conexion =  new ConexionAvw();
        ArrayList params = new ArrayList();
        int pos = 0;
        
        try {
            conexion.abrirConexion();
            conexion.startTransaction();

            //Obtengo el codigo con el q debo insertar
            sql.setLength(0); //Limpio la cadena
            sql.append("SELECT caw_codigo.nextval FROM dual");
            rs = conexion.getPreparedStatementResultSet(sql, null);
            logger.info(sql.toString());
            rs.next();
            String codigo = Utiles.noNull(rs.getObject(1));
            
            sql.setLength(0); //Limpio la cadena
            sql.append("INSERT INTO ");
            sql.append("categorias_web( ");
            sql.append("caw_codigo, ");
            sql.append("caw_nombre, ");
            sql.append("caw_categoria_padre, ");
            sql.append("caw_palabras_claves ");
            sql.append(") ");
            sql.append("VALUES(?,?,?,?) ");
            
            params.add(new BoundParam(++pos,codigo,java.sql.Types.NUMERIC));
            params.add(new BoundParam(++pos,categoriaWeb.getCawNombre(),java.sql.Types.VARCHAR));
            params.add(new BoundParam(++pos,categoriaWeb.getCawCategoriaPadre().getCawCodigo(),java.sql.Types.VARCHAR));
            params.add(new BoundParam(++pos,categoriaWeb.getCawPalabrasClaves(),java.sql.Types.VARCHAR));
            
            logger.info("INSERTO Categorias");
            logger.info(sql.toString());
            conexion.executePreparedStatement(sql, params);
            
            
            sql.setLength(0); //Limpio la cadena
            sql.append("INSERT INTO ");
            sql.append("relacion_categorias_web( ");
            sql.append("caw_codigo_padre, ");
            sql.append("caw_codigo_hijo ");
            sql.append(") ");
            sql.append("VALUES(?,?) ");
                
            
            for (CategoriaWeb categoria: categoriaWeb.getCawCategoriaRelacion()) {
                pos=0;
                params.clear();
                params.add(new BoundParam(++pos,codigo,java.sql.Types.VARCHAR));
                params.add(new BoundParam(++pos,categoria.getCawCodigo(),java.sql.Types.VARCHAR));
                
                logger.info("INSERTO Categorias");
                logger.info(sql.toString());  
                conexion.executePreparedStatement(sql, params);
            }
            
            conexion.commitTransaction();
        } catch (SQLException e) {
            try {
                conexion.rollbackTransaction();
            } catch (SQLException ex) {
                logger.log(Level.SEVERE,e.getMessage(),ex);
            }
            logger.log(Level.SEVERE,e.getMessage(),e);
            throw new AvwException(e);
        } finally {
            conexion.cerrarConexion();
        }
    }
    
    /**
     * Modifica en el sistema la Categoria pasado por parametro.
     * @return objeto CategoriaWeb con el objeto CategoriaWeb padre
     * y el array de objetos CategoriaWeb de las categorias relacionadas.
     */
    public static void modificarCategoria(CategoriaWeb categoriaWeb)throws AvwException {
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        ConexionAvw conexion = new ConexionAvw();
        ArrayList params = new ArrayList();
        
        sql.append("UPDATE ");
        sql.append("categorias_web SET ");
        sql.append("caw_nombre = ?, ");
        sql.append("caw_categoria_padre = ?, ");
        sql.append("caw_palabras_claves = ? ");
        sql.append("WHERE ");
        sql.append("caw_codigo = ? ");
        
        params.add(new BoundParam(1,Utiles.noNull(categoriaWeb.getCawNombre()),java.sql.Types.VARCHAR));
        params.add(new BoundParam(2,Utiles.noNull(categoriaWeb.getCawCategoriaPadre().getCawCodigo()),java.sql.Types.VARCHAR));
        params.add(new BoundParam(3,Utiles.noNull(categoriaWeb.getCawPalabrasClaves()),java.sql.Types.VARCHAR));
        params.add(new BoundParam(4,Utiles.noNull(categoriaWeb.getCawCodigo()),java.sql.Types.NUMERIC));
        
        try {
            conexion.abrirConexion();
            conexion.startTransaction();
            logger.info("UPDATE Categorias");
            logger.info(sql.toString());
            conexion.executePreparedStatement(sql.toString(),params);
            
            sql.setLength(0); //Limpio la cadena
            sql.append("DELETE FROM ");
            sql.append("relacion_categorias_web ");
            sql.append("WHERE ");
            sql.append("caw_codigo_padre = ? ");
            params.clear();
            params.add(new BoundParam(1,Utiles.noNull(categoriaWeb.getCawCodigo()),java.sql.Types.NUMERIC));
            
            logger.info("DELETE Categorias relacionadas");
            logger.info(sql.toString());
            conexion.executePreparedStatement(sql, params);
            
            for (CategoriaWeb categoria: categoriaWeb.getCawCategoriaRelacion()) {
                sql.setLength(0); //Limpio la cadena
                sql.append("INSERT INTO ");
                sql.append("relacion_categorias_web( ");
                sql.append("caw_codigo_padre, ");
                sql.append("caw_codigo_hijo ");
                sql.append(") VALUES(?,?) ");
                
                params.clear();
                params.add(new BoundParam(1,Utiles.noNull(categoriaWeb.getCawCodigo()),java.sql.Types.NUMERIC));
                params.add(new BoundParam(2,Utiles.noNull(categoria.getCawCodigo()),java.sql.Types.NUMERIC));
                
                logger.info("INSERTO Categorias relacionadas");
                logger.info(sql.toString());
                conexion.executePreparedStatement(sql,params);
            }
            conexion.commitTransaction();
        } catch (SQLException e) {
            try {
                conexion.rollbackTransaction();
            } catch (SQLException ex) {
                logger.log(Level.SEVERE,e.getMessage(),ex);
            }
            logger.log(Level.SEVERE,e.getMessage(),e);
            throw new AvwException(e);
            
        } finally {
            conexion.cerrarConexion();
        }
    }
    
    /**
     * Se elimina la categoria y todas las relaciones
     * entre categorias que posee la misma.
     * @param objeto CategoriaWeb (con solo codigo).
     */
    public static void eliminarCategoria(CategoriaWeb categoriaWeb)throws AvwException {
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        ConexionAvw conexion = new ConexionAvw();
        ArrayList params = new ArrayList();
        
        try {
            conexion.abrirConexion();
            conexion.startTransaction();
            /*Elimina toda relacion existente*/
            sql.setLength(0); //Limpio la cadena
            sql.append("DELETE FROM ");
            sql.append("relacion_categorias_web ");
            sql.append("WHERE ");
            sql.append("caw_codigo_padre = ? ");
            params.clear();
            params.add(new BoundParam(1,Utiles.noNull(categoriaWeb.getCawCodigo()),java.sql.Types.NUMERIC));
            
            logger.info("DELETE Categorias relacionadas");
            logger.info(sql.toString());
            conexion.executePreparedStatement(sql, params);
            
            /*Elimina finalmente la categoria*/
            sql.setLength(0); //Limpio la cadena
            sql.append("DELETE FROM ");
            sql.append("categorias_web ");
            sql.append("WHERE ");
            sql.append("caw_codigo = ? ");
            params.clear();
            params.add(new BoundParam(1,Utiles.noNull(categoriaWeb.getCawCodigo()),java.sql.Types.NUMERIC));
            
            logger.info("DELETE Categorias");
            logger.info(sql.toString());
            conexion.executePreparedStatement(sql, params);
            
            conexion.commitTransaction();
        } catch (SQLException e) {
            try {
                conexion.rollbackTransaction();
            } catch (SQLException ex) {
                logger.log(Level.SEVERE,e.getMessage(),ex);
            }
            logger.log(Level.SEVERE,e.getMessage(),e);
            throw new AvwException(e);            
        } finally {
            conexion.cerrarConexion();
        }
    }
    
    /**
     * Obtener CategoriaWeb a partir del codigo del objeto
     * CategoriaWeb pasada por parametros.
     * @param objeto CategoriaWeb (con solo el codigo).
     * @return objeto CategoriaWeb.
     */
    public static CategoriaWeb obtenerCategoria(CategoriaWeb categoriaWeb) throws AvwException {
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        ArrayList params = new ArrayList();
        ConexionAvw conexion = new ConexionAvw();
        
        sql.append("SELECT ");
        sql.append("cw.caw_codigo, ");
        sql.append("cw.caw_nombre, ");
        sql.append("cw.caw_categoria_padre, ");
        sql.append("cw.caw_palabras_claves, ");
        sql.append("cwp.caw_codigo, ");
        sql.append("cwp.caw_nombre ");
        sql.append("FROM ");
        sql.append("categorias_web cw, ");
        sql.append("categorias_web cwp ");
        sql.append("WHERE ");
        sql.append("cw.caw_codigo = ? ");
        sql.append("AND ");
        sql.append("cw.caw_categoria_padre = cwp.caw_codigo (+) ");
        
        params.add(new BoundParam(1,Utiles.noNull(categoriaWeb.getCawCodigo()),java.sql.Types.NUMERIC));
        try {
            conexion.abrirConexion();
            logger.info("Obtengo Categoria ");
            logger.info(sql.toString());
            rs = conexion.getPreparedStatementResultSet(sql,params);            
            rs.next();
            categoriaWeb.setCawNombre(rs.getString(2));
            CategoriaWeb categoriaPadre = new CategoriaWeb(rs.getString(3));
            categoriaPadre.setCawNombre(rs.getString(6));
            categoriaWeb.setCawCategoriaPadre(categoriaPadre);
            categoriaWeb.setCawPalabrasClaves(rs.getString(4));
            
        } catch (SQLException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            throw new AvwException(e);
        } finally {
            conexion.cerrarConexion();
        }
        
        return categoriaWeb;
    }
    
    /**
     * Obtener una lista de las categorias que no poseen categorias hijas.
     * @return ArrayList de objetos CategoriaWeb.
     */
    public static ArrayList<CategoriaWeb> listarCategoriasSinCategoriasHijas() throws AvwException {
        ArrayList<CategoriaWeb> categorias = new ArrayList();
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        ConexionAvw conexion = new ConexionAvw();
        
        sql.append("SELECT ");
        sql.append("c1.caw_codigo, ");
        sql.append("c1.caw_nombre, ");
        sql.append("c1.caw_categoria_padre, ");
        sql.append("c1.caw_palabras_claves ");
        sql.append("FROM categorias_web c1 ");
        sql.append("WHERE NOT EXISTS( ");
        sql.append("SELECT ");
        sql.append("c2.caw_categoria_padre ");
        sql.append("FROM categorias_web c2 ");
        sql.append("WHERE ");
        sql.append("c2.caw_categoria_padre = c1.caw_codigo ");
        sql.append(") ");
        sql.append("ORDER BY c1.caw_nombre ");
        
        try {
            logger.info("Consulto Categorias sin categorias hijas");
            logger.info(sql.toString());
            conexion.abrirConexion();
            rs = conexion.getPreparedStatementResultSet(sql, null);
            
            while (rs.next()) {
                CategoriaWeb categoriaWeb = new CategoriaWeb();
                categoriaWeb.setCawCodigo(rs.getString("caw_codigo"));
                categoriaWeb.setCawNombre(rs.getString("caw_nombre"));
                categoriaWeb.setCawCategoriaPadre(new CategoriaWeb(rs.getString("caw_categoria_padre")));
                categoriaWeb.setCawPalabrasClaves(rs.getString("caw_palabras_claves"));
                
                categorias.add(categoriaWeb);
            }
            
        } catch (SQLException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            throw new AvwException(e);
        } finally {
            conexion.cerrarConexion();
        }
        return categorias;
    }
    
    /**
     * ArrayList de objetos CategoriaWeb por el codigo de categoria padre
     * que se pasa por parametro en un objeto CategoriaWeb
     * (-1 es el codigo para obtener las categorias padres)
     * y que ademas, dicha categoria, posee algun articulo asociado a la
     * campania tambien pasada por parametro.
     * @param: objeto CategoriaWeb (con solo el codigo).
     * @param: objeto CampaniaWeb (con solo el codigo).
     */
public static ArrayList<CategoriaWeb> listarCategoriasPorPadreYCampania(CategoriaWeb categoriaWeb, CampaniaWeb campaniaWeb) throws AvwException {
        ArrayList<CategoriaWeb> categorias = new ArrayList<CategoriaWeb> ();
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        ConexionAvw conexion = new ConexionAvw();
        ArrayList params = null;
        
        try {
            sql.append("SELECT ");
            sql.append("cw.caw_codigo, ");
            sql.append("cw.caw_nombre ");
            sql.append("FROM categorias_web cw ");
            sql.append("WHERE ");
            
            if (categoriaWeb.getCawCodigo().equals("-1")) {
                sql.append("cw.caw_categoria_padre IS NULL");
            } else {
                sql.append("cw.caw_categoria_padre = ?");
                params = new ArrayList();
                params.add(new BoundParam(1,Utiles.noNull(categoriaWeb.getCawCodigo()),java.sql.Types.NUMERIC));
            }
            sql.append(" ORDER BY cw.caw_nombre");
            
            conexion.abrirConexion();
            
            rs = conexion.getPreparedStatementResultSet(sql, params);
            while (rs.next()) {
                CategoriaWeb categoria =
                        new CategoriaWeb(rs.getString("caw_codigo"));
                categoria.setCawNombre(rs.getString("caw_nombre"));
                logger.info(categoria.getCawNombre());
                categorias.add(categoria);
            }
            
            
        } catch (SQLException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            throw new AvwException(e);
        } finally {
            conexion.cerrarConexion();
        }
        
        return categorias;
    }

/**
 * ArrayList de objetos CategoriaWeb por el codigo de categoria padre
 * que se pasa por parametro en un objeto CategoriaWeb
 * (-1 es el codigo para obtener las categorias padres)
 * y que ademas, en el caso de que la categoria no sea padre, 
 * posee algun articulo asociado a la
 * campania tambien pasada por parametro.
 * @param: objeto CategoriaWeb (con solo el codigo).
 * @param: objeto CampaniaWeb (con solo el codigo).
 */
public static ArrayList<CategoriaWeb> listarCategoriasPorPadreYCampaniaConArticulos(
        CategoriaWeb categoriaWeb, CampaniaWeb campaniaWeb) throws AvwException {
        ArrayList<CategoriaWeb> categorias = new ArrayList<CategoriaWeb> ();
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        ConexionAvw conexion = new ConexionAvw();
        ArrayList params =  new ArrayList();;
        int pos = 0 ;
        try {

            sql.append("SELECT distinct(cw.caw_codigo),  ");
            sql.append("cw.caw_nombre  ");

            if (categoriaWeb.getCawCodigo().equals("-1")) {
                sql.append("FROM categorias_web cw ");
                sql.append("WHERE ");
                sql.append(" cw.caw_categoria_padre IS NULL");
            } else {
                sql.append("FROM categorias_web cw, articulos_categorias_web acw, articulos_avw art  ");
                sql.append("WHERE acw.art_codigo = art.art_codigo  ");
                sql.append("AND   acw.caw_codigo = cw.caw_codigo ");
                sql.append("AND art.cam_codigo = ? ");
                sql.append("AND cw.caw_categoria_padre = ? ");
                params.add(new BoundParam(++pos,Utiles.noNull(campaniaWeb.getCamCodigo()),java.sql.Types.NUMERIC));
                params.add(new BoundParam(++pos,Utiles.noNull(categoriaWeb.getCawCodigo()),java.sql.Types.NUMERIC));
            }
            sql.append(" ORDER BY cw.caw_nombre");
            
            conexion.abrirConexion();
            rs = conexion.getPreparedStatementResultSet(sql, params);
            while (rs.next()) {
                CategoriaWeb categoria =
                        new CategoriaWeb(rs.getString("caw_codigo"));
                categoria.setCawNombre(rs.getString("caw_nombre"));
                logger.info(categoria.getCawNombre());
                categorias.add(categoria);
            }
            
            
        } catch (SQLException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            throw new AvwException(e);
        } finally {
            conexion.cerrarConexion();
        }
        
        return categorias;
    }

    

    /**
     * Obtiene la categoria que es padre del objeto CategoriaWeb
     * pasado por parametro.
     * @param CategoriaWeb (con solo el codigo).
     * @return objeto CategoriaWeb.
     */
    public static CategoriaWeb obtenerCategoriaPorHijo(CategoriaWeb categoriaWeb) throws AvwException {
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        CategoriaWeb categoriaPadre = new CategoriaWeb();
        ConexionAvw conexion = new ConexionAvw();
        ArrayList params = new ArrayList();
        
        sql.append("SELECT ");
        sql.append("cawp.caw_codigo, ");
        sql.append("cawp.caw_nombre, ");
        sql.append("cawp.caw_categoria_padre, ");
        sql.append("cawp.caw_palabras_claves ");
        sql.append("FROM ");
        sql.append("categorias_web cawh, ");
        sql.append("categorias_web cawp ");
        sql.append("WHERE ");
        sql.append("cawp.caw_codigo = cawh.caw_categoria_padre ");
        sql.append("AND cawh.caw_codigo = ?");
        params.add(new BoundParam(1,Utiles.noNull(categoriaWeb.getCawCodigo()),java.sql.Types.NUMERIC));
                
        try {
            conexion.abrirConexion();
            logger.info(sql.toString());
            rs = conexion.getPreparedStatementResultSet(sql, params);
            logger.info("Devuelve la consulta");
            rs.next();
            categoriaPadre.setCawCodigo(rs.getString("caw_codigo"));
            categoriaPadre.setCawNombre(rs.getString("caw_nombre"));
            categoriaPadre.setCawCategoriaPadre(new CategoriaWeb(rs.getString("caw_categoria_padre")));
            categoriaPadre.setCawPalabrasClaves(rs.getString("caw_palabras_claves"));
            
        } catch (SQLException e) {
            logger.log(Level.SEVERE,e.getMessage(),e);
            throw new AvwException(e);
        } finally {
            conexion.cerrarConexion();
        }
        
        return categoriaPadre;
    }
    
        
    /**
     *Return: array de objetos CategoriaWeb por el codigo de categoria padre y 
     * la marca que se pasa por parametro en un objeto CategoriaWeb  
     * (-1 es el codigo para obtener las categorias padres) 
     * y que ademas, en el caso de que la categoria no sea padre, 
     * posee algun articulo asociado a la campania tambien pasada por parametro.
     * Parametro: objeto CampaniaWeb (con solo el codigo) , un objeto CategoriaWeb
     * (con solo el codigo de la categoria padre) y 
     * objeto Marca (con solo el codigo o -1 si no se busca por marca).
     **/
    public static ArrayList<CategoriaWeb> listarCategoriasPorPadreYCampaniaYMarcaConArticulos 
            (CampaniaWeb campaniaWeb, CategoriaWeb categoriaWeb, Marca marca) throws AvwException {
        ArrayList<CategoriaWeb> categorias = new ArrayList<CategoriaWeb>();
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        ConexionAvw conexion = new ConexionAvw();
        ArrayList params = new ArrayList();
        int pos =0;
        Recurso procedimiento = new Recurso("categoriadal.properties");
        try {
            logger.info("Consulto Categorias para los menu ");
            params.add(new ParamCallable(++pos,null,OracleTypes.CURSOR,ParamCallable.OUT));
            params.add(new ParamCallable(++pos,campaniaWeb.getCamCodigo(),OracleTypes.VARCHAR,ParamCallable.IN));
                
            
            conexion.abrirConexion();
            rs = conexion.getCallableStatement(procedimiento.obtenerPropiedad("listarCategoriasPorPadreYCampaniaYMarcaConArticulos"),params,1);
            
            while (rs.next()) {
                CategoriaWeb categoria = new CategoriaWeb();
                categoria.setCawCodigo(Utiles.noNull(rs.getString("caw_codigo")));
                categoria.setCawNivel(rs.getInt("nivel"));
                categoria.setCawNombre(Utiles.noNull(rs.getString("caw_nombre")));
                categoria.setCawCategoriaPadre(new CategoriaWeb(Utiles.noNull(rs.getString("caw_categoria_padre"))));

                categorias.add(categoria);
            }
        } catch (SQLException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            throw new AvwException(e);
        } finally {
            conexion.cerrarConexion();
        }
        
        return categorias;
    }
    /**
     * Obtener las categorias relacionadas a la categoria pasada por parametros.
     * @param: objeto CategoriaWeb (con solo el codigo).
     * @return: ArrayList de objetos CategoriaWeb
     */
    public static ArrayList<CategoriaWeb> obtenerCategoriasRelacionadas(CategoriaWeb categoriaWeb) throws AvwException {
        ArrayList<CategoriaWeb> categorias = new ArrayList<CategoriaWeb>();
        StringBuilder sql = new StringBuilder();
        ResultSet rs;
        ConexionAvw conexion = new ConexionAvw();
        ArrayList params = new ArrayList();
        
        sql.append("SELECT ");
        sql.append("caw.caw_codigo, ");
        sql.append("caw.caw_nombre, ");
        sql.append("caw.caw_categoria_padre, ");
        sql.append("caw.caw_palabras_claves ");
        sql.append("FROM categorias_web caw ");
        sql.append("WHERE caw.caw_codigo ");
        sql.append("IN( ");
        sql.append("SELECT ");
        sql.append(" rcw.caw_codigo_hijo ");
        sql.append("FROM relacion_categorias_web rcw ");
        sql.append("WHERE rcw.caw_codigo_padre = ? ");
        sql.append(")");
        params.add(new BoundParam(1,categoriaWeb.getCawCodigo(),OracleTypes.NUMERIC));
                
        try {
            conexion.abrirConexion();
            logger.info("Consulto Categorias relacionadas ");
            logger.info(sql.toString());
            rs = conexion.getPreparedStatementResultSet(sql, params);
            
            while (rs.next()) {
                CategoriaWeb categoria = new CategoriaWeb();
                categoria.setCawCodigo(Utiles.noNull(rs.getString("caw_codigo")));
                categoria.setCawNombre(Utiles.noNull(rs.getString("caw_nombre")));
                categoria.setCawCategoriaPadre(new CategoriaWeb(Utiles.noNull(rs.getString("caw_categoria_padre"))));
                categoria.setCawPalabrasClaves(Utiles.noNull(rs.getString("caw_palabras_claves")));
                
                categorias.add(categoria);
            }
        } catch (SQLException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            throw new AvwException(e);
        } finally {
            conexion.cerrarConexion();
        }
        
        return categorias;
    }
    
    /**
     * Retorna todos los codigos de categorias hojas de la categoria pasada
     * por parametro
     * @param cawCodigo codigo de categoria web
     * @return String con los codigo de categoria hojas separadas por coma
     */
    public static String obtenerCategoriasHojasPorCategoriaWeb(String cawCodigo) throws AvwException{
        StringBuilder categorias = new StringBuilder();
        StringBuilder sql = new StringBuilder();
        String categoria;
        String hijas;
        ResultSet rs;
        ConexionAvw conexion = new ConexionAvw();
        ArrayList params = new ArrayList();
        
        sql.append("SELECT ");
        sql.append("caw_codigo ");
        sql.append("FROM categorias_web ");
        sql.append("WHERE caw_categoria_padre = ?");
        params.add(new BoundParam(1,Utiles.noNull(cawCodigo),java.sql.Types.NUMERIC));

        try {
            conexion.abrirConexion();
            logger.info("Consulto las categorias hojas");
            rs = conexion.getPreparedStatementResultSet(sql, params);
            
            while (rs.next()) {
                categorias.append(CategoriaDAL.obtenerCategoriasHojasPorCategoriaWeb(
                        rs.getString("caw_codigo")));
            }
            
            if (categorias.toString().equals("")){
                categorias.append(cawCodigo + ",");
            }
            
        } catch (SQLException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            throw new AvwException(e);
        } finally {
            conexion.cerrarConexion();
        }
        return categorias.toString();
    }

}
